package feevale.boteco.bean;

import feevale.boteco.util.Agente;

public class Garcon extends Agente implements Runnable {
	
	private Integer id;
	
	private Thread thread;
	
	private Geladeira geladeira;
	
	public Garcon() {
		this.thread = new Thread(this);
		this.thread.start();
	}
	
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}
	
	@Override
	public String getNome() {
		return "Garçon " + this.id;
	}
	
	/**
	 * Verifica se está alocado para abastecer uma geladeira, caso estiver abre a porta da mesma para 
	 * realizar o abastecimento.
	 */
	@Override
	public void run() {
		
		while (true) {
			
			try {
				Thread.sleep(100);
				
				if (estaAlocado()) {
					geladeira.abrirPorta(this);
				}
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Abre a geladeira para repor cervejas.
	 * Atualiza dados de acompanhamento do processo.
	 * Dispensa o garçon, retornando-o mesmo para a fila de garçons disponíveis no boteco.
	 */
	@Override
	public void abreGeladeira(Geladeira geladeira) {
		
		try {
			geladeira.atualizaSituacao(getNome() + " abastecendo a geladeira!");
			
			for (int i = geladeira.getCervejas().size(); i < Boteco.DEFAULT_CAPACIDADE_MAXIMA; i++) {
				Double tempo = getTempoReposicao();
				
				geladeira.atualizaTempoAgente(tempo / 1000);
				
				Thread.sleep(tempo.longValue());
				
				reporCeva(geladeira);
			}
			
			geladeira.atualizaSituacao("");
			geladeira.atualizaTempoAgente(null);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Insere uma nova cerveja na geladeira.
	 * @param geladeira
	 */
	private void reporCeva(Geladeira geladeira) {
		Cerveja cerveja = new Cerveja();
		cerveja.setId(geladeira.getIdx());
		cerveja.setTipoCerveja(geladeira.getTipoCerveja());
		
		geladeira.getCervejas().offer(cerveja);
		geladeira.atualizaTableCervejas();
		
		geladeira.incrementIdx();
	}
	
	/**
	 * Ao deixar de abastecer a geladeira, volta para a fila de garçons disponíveis do boteco.
	 */
	@Override
	public void fechaGeladeira(Geladeira geladeira) {
		
		setGeladeira(null);
		Boteco.GARCONS.offer(this);
		
		geladeira.removeGarcon();
	}
	
	/**
	 * Retorna o tempo (randômico) de reposição de uma cerveja na geladeira, limitando ao intervalo definido na parametrização.
	 * @return
	 */
	private static Double getTempoReposicao() {
		return getTime(Boteco.DEFAULT_TEMPO_REPOSICAO_INICIAL, Boteco.DEFAULT_TEMPO_REPOSICAO_FINAL);
	}
	
	public void setGeladeira(Geladeira geladeira) {
		this.geladeira = geladeira;
	}
	
	/**
	 * Verifica se está alocado para abastecer uma geladeira.
	 * @return
	 */
	public boolean estaAlocado() {
		return this.geladeira != null;
	}
	
}
